/**
 * @file protocol.c
 * @brief 蓝牙灯带板协议解析
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2021-02-01
 * @copyright Copyright (c) 2021  烽火通信
 */ 
#include "stdint.h"
#include "drv_led_v2.h"
#include "nrf_log.h"
#include "pcu.h"
// #include "bsp_fds.h"
#include "bsp_fstorage.h"
#include "FreeRTOS.h"
#include "task.h"

#define FRAME_LENGTH    50


/** @brief 组帧结构体 */
typedef struct PcuPack_s
{
    uint16_t pack_head; ///< 包头
    uint8_t pack_pos;   ///< 包组帧偏移
    uint8_t pack_len;   ///< 包长
    uint8_t pack_buff[FRAME_LENGTH];    ///< 包缓存
    
} Pack_t;

static Pack_t ble_pack;

/**
 * @brief 校验和计算
 * @param  data         要计算数据的起始地址
 * @param  len          要计算数据的长度
 * @return uint8_t 校验和结果
 */
static uint8_t calc_csum(uint8_t *data, uint16_t len)
{
    uint32_t pack_CSUM = 0;
    uint16_t i;

    for(i=0; i<len; i++)
        pack_CSUM = pack_CSUM + data[i];

    return (uint8_t)pack_CSUM;
}

extern LedDrv_t led_obj;
extern LedSet_t g_ledset;

static void light_protocol_handle( Pack_t *pmsg )
{
    RGB_t loop_color[LED_LOOP_SIZE];
    uint8_t i;

    memset(loop_color, 0, sizeof(RGB_t)*7);

    NRF_LOG_INFO("light package recv length = %d\r\n", pmsg->pack_len);
    NRF_LOG_RAW_HEXDUMP_INFO(pmsg->pack_buff, pmsg->pack_len);
    NRF_LOG_RAW_INFO("\r\n");

    /* 校验和检查TODO:待添加 */
    calc_csum(&pmsg->pack_buff[2], pmsg->pack_len - 3);

    switch (pmsg->pack_buff[3])
    {
    case 0x01:  /* 单色模式 LED_KEEP_MODE */
    {
        for (i=0; i<pmsg->pack_buff[5]; i++)
        {
            loop_color[i].r = pmsg->pack_buff[i*3+6];
            loop_color[i].g = pmsg->pack_buff[i*3+7];
            loop_color[i].b = pmsg->pack_buff[i*3+8];
        }
        led_set( &led_obj, loop_color, pmsg->pack_buff[5], LED_KEEP_MODE, NULL, NULL);

        g_ledset.mode = LED_KEEP_MODE;
        g_ledset.rgb_loop_num = pmsg->pack_buff[5];
        memcpy(g_ledset.rgb_loop, loop_color, sizeof(RGB_t)*7);
        // my_fds_write(PCU_FILE, PCU_LIGHT_SET_REC_KEY, &g_ledset, sizeof(LedSet_t));
        my_fstorage_write(PCU_LIGHT_SET_ADDR, &g_ledset, sizeof(LedSet_t));
    } break;

    case 0x02:  /* 闪烁模式 LED_BLINK_MODE */
    {
        for (i=0; i<pmsg->pack_buff[6]; i++)
        {
            loop_color[i].r = pmsg->pack_buff[i*3+7];
            loop_color[i].g = pmsg->pack_buff[i*3+8];
            loop_color[i].b = pmsg->pack_buff[i*3+9];
        }
        led_set( &led_obj, loop_color, pmsg->pack_buff[6], LED_BLINK_MODE, NULL, pmsg->pack_buff[5] * 10);

        g_ledset.mode = LED_BLINK_MODE;
        g_ledset.rgb_loop_num = pmsg->pack_buff[6];
        memcpy(g_ledset.rgb_loop, loop_color, sizeof(RGB_t)*7);
        g_ledset.speed = pmsg->pack_buff[5] * 10;
        // my_fds_write(PCU_FILE, PCU_LIGHT_SET_REC_KEY, &g_ledset, sizeof(LedSet_t));
        my_fstorage_write(PCU_LIGHT_SET_ADDR, &g_ledset, sizeof(LedSet_t));
    } break;

    case 0x03:  /* 流水模式 LED_WATER_MODE */
    {
        for (i=0; i<pmsg->pack_buff[6]; i++)
        {
            loop_color[i].r = pmsg->pack_buff[i*3+7];
            loop_color[i].g = pmsg->pack_buff[i*3+8];
            loop_color[i].b = pmsg->pack_buff[i*3+9];
        }
        led_set( &led_obj, loop_color, pmsg->pack_buff[6], LED_WATER_MODE, NULL, pmsg->pack_buff[5] * 10);

        g_ledset.mode = LED_WATER_MODE;
        g_ledset.rgb_loop_num = pmsg->pack_buff[6];
        memcpy(g_ledset.rgb_loop, loop_color, sizeof(RGB_t)*7);
        g_ledset.speed = pmsg->pack_buff[5] * 10;
        // my_fds_write(PCU_FILE, PCU_LIGHT_SET_REC_KEY, &g_ledset, sizeof(LedSet_t));
        my_fstorage_write(PCU_LIGHT_SET_ADDR, &g_ledset, sizeof(LedSet_t));
    } break;

    case 0x04:  /* 渐变模式 LED_GRADUAL_MODE */
    {
        loop_color[0].r = 0;
        loop_color[0].g = 255;
        loop_color[0].b = 0;

        g_ledset.mode = LED_GRADUAL_MODE;
        g_ledset.rgb_loop_num = 1;
        memcpy(g_ledset.rgb_loop, loop_color, sizeof(RGB_t));
        g_ledset.step = pmsg->pack_buff[6];
        g_ledset.speed = pmsg->pack_buff[5] * 10;

        NRF_LOG_INFO("light mode=%d  rgb_loop_num=%d  step=%d  speed=%d\r\n", g_ledset.mode, g_ledset.rgb_loop_num, g_ledset.step, g_ledset.speed);
        led_set( &led_obj, &loop_color[0], 1, LED_GRADUAL_MODE, g_ledset.speed, g_ledset.step );
        NRF_LOG_INFO("light mode=%d  rgb_loop_num=%d  step=%d  speed=%d\r\n", g_ledset.mode, g_ledset.rgb_loop_num, g_ledset.step, g_ledset.speed);

        // my_fds_write(PCU_FILE, PCU_LIGHT_SET_REC_KEY, &g_ledset, sizeof(LedSet_t));
        my_fstorage_write(PCU_LIGHT_SET_ADDR, &g_ledset, sizeof(LedSet_t));
    } break;

#if (LED_BRIGHTNESS_LEVEL == LED_BRIGHTNESS_4096)
    case 0x05:  /* RGB电流 */
    {
        g_ledset.current = (pmsg->pack_buff[5]&0x0F);
        led_set_cur(&led_obj, g_ledset.current, g_ledset.current, g_ledset.current);

        // my_fds_write(PCU_FILE, PCU_LIGHT_SET_REC_KEY, &g_ledset, sizeof(LedSet_t));
        my_fstorage_write(PCU_LIGHT_SET_ADDR, &g_ledset, sizeof(LedSet_t));
    } break;
#endif

    case 0xFE:  /* 复位 */
    {
        NVIC_SystemReset();
    } break;
    
    default:
        break;
    }
}



#if 1
/**
 * @brief 蓝牙接收组帧
 */
void ble_rev_package( uint8_t * data, uint16_t len )
{
    uint16_t i;

    for ( i=0; i<len; i++ )
    {
        switch (ble_pack.pack_pos)
        {
        case 0:     /* 帧头第一个数据 */
            if (data[i] == 0x55)
            {
                ble_pack.pack_buff[ble_pack.pack_pos] = data[i];
                ble_pack.pack_pos++;
            }
            break;

        case 1:     /* 帧头第2个数据 */
            if ( data[i] == 0x79 )
            {
                #if PCU_PACK_TIMEOUT_CHECK_EN
                app_timer_start(blePack_timer_id, APP_TIMER_TICKS(PCU_PACK_TIMEOUT, 0), NULL);
                #endif
                ble_pack.pack_buff[ble_pack.pack_pos] = data[i];
                ble_pack.pack_pos++;
            }
            else
            {
                memset( &ble_pack, 0, sizeof(Pack_t) );
                if (data[i] == 0xFF)
                {
                    ble_pack.pack_buff[ble_pack.pack_pos] = data[i];
                    ble_pack.pack_pos++;
                }
            }
            break;

        default:
            if ( (ble_pack.pack_pos >= 2) && (ble_pack.pack_pos < 4) )
            {
                ble_pack.pack_buff[ble_pack.pack_pos] = data[i];
                ble_pack.pack_pos++;
            }
            else if (ble_pack.pack_pos == 4)    /* 获取长度 */
            {
                ble_pack.pack_buff[ble_pack.pack_pos] = data[i];
                ble_pack.pack_pos++;
                ble_pack.pack_len = data[i] + 6;
                if (ble_pack.pack_len > FRAME_LENGTH)
                {
                    memset( &ble_pack, 0, sizeof(Pack_t) );
                }
            }
            else if ( (ble_pack.pack_pos >= 5) && (ble_pack.pack_pos < (ble_pack.pack_len-1)) )
            {
                ble_pack.pack_buff[ble_pack.pack_pos] = data[i];
                ble_pack.pack_pos++;
            }
            else if (ble_pack.pack_pos == (ble_pack.pack_len-1)) /* 校验位 */
            {
                ble_pack.pack_buff[ble_pack.pack_pos] = data[i];

                /* TODO:组帧完成，转义处理 */

                #if PCU_PACK_TIMEOUT_CHECK_EN
                app_timer_stop(blePack_timer_id);
                #endif
                NRF_LOG_RAW_INFO("ble_package ok\r\n");

                light_protocol_handle( &ble_pack );

                memset( &ble_pack, 0, sizeof(Pack_t) );
            }
            break;
        }
    }
}
#endif


/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/
